package com.ld.shieldsb.common.core;

import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;

import com.ld.shieldsb.common.core.util.StringUtils;

import lombok.extern.slf4j.Slf4j;

@Slf4j
public abstract class ServiceFactory<T> {
    @SuppressWarnings({ "rawtypes" })
    private static final Map<Class<? extends ServiceFactory>, ServiceFactory> INSTANCES_MAP = new HashMap<Class<? extends ServiceFactory>, ServiceFactory>();

    protected final Map<String, T> SERVICE_MAP = new LinkedHashMap<>(); // 存放对象缓存
    protected final Map<String, Class<? extends T>> SERVICE_CLASS_MAP = new LinkedHashMap<>(); // 类对象map，key为不同数据库的key

    static {
        // 注意工厂类不要一开始就注册对象，否则可能缺少必要的jar包不能实例化报错，应该注册类
    }

    @SuppressWarnings("unchecked")
    public static <T> ServiceFactory<T> getInstance(Class<? extends ServiceFactory<T>> clz) {
        ServiceFactory<T> obj = INSTANCES_MAP.get(clz);
        if (obj == null) {
            synchronized (INSTANCES_MAP) {
                obj = INSTANCES_MAP.get(clz);
                if (obj == null) {
                    try {
                        obj = clz.newInstance();
                        INSTANCES_MAP.put(clz, obj);
                    } catch (InstantiationException | IllegalAccessException e) {
                        log.error("", e);
                    }
                }
            }
        }
        return obj;
    }

    // 其他需要注册的类，可以在具体项目中注册，注意需要在调用前加入
    public void registerServiceClass(String key, Class<? extends T> clses) {
        if (StringUtils.isNoneBlank(key)) {
            SERVICE_CLASS_MAP.put(key, clses);
        } else {
            log.error("key不能为空！");
        }
    }

    /**
     * 
     * 获取service实例对象，使用缓存
     * 
     * @Title getService
     * @author 吕凯
     * @date 2019年10月23日 下午2:04:12
     * @param key
     * @return VerifyCodeService
     */
    public T getService(String key) {
        return getService(key, true);
    }

    /**
     * 获取所有key
     * 
     * @Title getAllKey
     * @author 吕凯
     * @date 2019年10月31日 上午10:19:55
     * @return Set<String>
     */
    public Set<String> getAllKey() {
        return SERVICE_CLASS_MAP.keySet();
    }

    /**
     * 
     * 获取service实例对象
     * 
     * @Title getService
     * @author 吕凯
     * @date 2019年10月23日 下午2:03:42
     * @param key
     * @param useCache
     *            是否缓存
     * @return VerifyCodeService
     */
    public T getService(String key, boolean useCache) {
        if (!useCache) {
            return getServiceInstance(key); // 不使用缓存则每次new
        }
        T service = null;
        if (StringUtils.isNotBlank(key)) {
            service = SERVICE_MAP.get(key);
            if (service == null) {
                synchronized (SERVICE_MAP) {
                    service = SERVICE_MAP.get(key);
                    if (service == null) { // 双锁检查
                        service = getServiceInstance(key);
                        SERVICE_MAP.put(key, service);
                    }
                }
            }
        }
        return service;
    }

    /**
     * 获取service实例
     * 
     * @Title getServiceInstance
     * @author 吕凯
     * @date 2019年10月23日 下午2:02:25
     * @param key
     * @return VerifyCodeService
     */
    private T getServiceInstance(String key) {
        T service = null;
        if (StringUtils.isNotBlank(key)) {
            Class<? extends T> clazz = SERVICE_CLASS_MAP.get(key);
            if (clazz == null) {
                log.error("ServiceFactory中未注册" + key + "对应的类！");
            } else {
                try {
                    service = clazz.newInstance();
                } catch (InstantiationException | IllegalAccessException e) {
                    log.warn("获取service失败：" + clazz.getName());
                }
            }
        }
        return service;
    }

    /**
     * 移除服务类
     * 
     * @Title removeService
     * @author 吕凯
     * @date 2018年2月3日 下午12:35:05
     * @param key
     * @return boolean
     */
    public boolean removeService(String key) {
        Object service = SERVICE_MAP.get(key);
        if (service != null) {
            // 删除
            SERVICE_MAP.remove(key);
        }
        return true;
    }

    /**
     * 清空所有service
     * 
     * @Title clear
     * @author 吕凯
     * @date 2018年2月24日 上午9:07:57 void
     */
    public void clear() {
        synchronized (SERVICE_MAP) {
            SERVICE_MAP.clear();
        }
    }
}
